home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 8
/
Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso
/
Aminet
/
util
/
cdity
/
Yak210src.lha
/
Yak_2.10_Src
/
WBStartup
/
Unixdirs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-16
|
14KB
|
508 lines
/*
** Patches dos.library functions to allow use of '.' and '..' ala UNIX.
** Largely inspired from UnixDirsII from Martin Scott.
**
** List of patched functions :
**
** AssignLate
** AssignPath
** CreateDir
** DeleteFile
** LoadSeg
** Lock
** MakeLink
** MatchFirst
** NewLoadSeg
** Open
** ParsePattern
** Rename
** SetComment
** SetFileDate
** SetProtection
**
** Author: Gael Marziou
** Created: 14 July 94 (Bastille day ;-)
**
**
*/
#define __USE_SYSBASE
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <exec/semaphores.h>
#include <dos/dos.h>
#include <libraries/commodities.h>
#include <string.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include "Patch_Libs.h"
#include "yak.h"
#include "Settings.h"
/* Local protos */
SAVEDS BOOL adjustpath(UBYTE *path, UBYTE *newpath, LONG len);
/* The number of 'replacement' functions for UnixDirs feature */
#define UNIXDIRS_NUMBEROFFUNCTIONS (15)
/* declare stuff for standard one-parameter function */
/* UBYTE * in d1 */
#define DEC11_OLD(oldname) LONG (*ASM oldname) (REG(d1) UBYTE *, REG(a6) struct Library *base)
#define DEC11_NEW(newname) SAVEDS LONG ASM newname(REG(d1) UBYTE *, REG(a6) struct Library *base)
#define DEC11(name) DEC11_OLD(old## name); DEC11_NEW(new## name); DEC_LVO(LVO## name)
/* declare stuff for standard two-parameter function */
/* UBYTE * in d1 */
#define DEC21_OLD(oldname) LONG (*ASM oldname) (REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *base)
#define DEC21_NEW(newname) SAVEDS LONG ASM newname(REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *base)
#define DEC21(name) DEC21_OLD(old## name); DEC21_NEW(new## name); DEC_LVO(LVO## name)
/* declare stuff for standard two-parameter function */
/* UBYTE * in d2 */
#define DEC22_OLD(oldname) LONG (*ASM oldname) (REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *base)
#define DEC22_NEW(newname) SAVEDS LONG ASM newname(REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *base)
#define DEC22(name) DEC22_OLD(old## name); DEC22_NEW(new## name); DEC_LVO(LVO## name)
/* the patched functions themselves */
DEC22(AssignLate);
DEC22(AssignPath);
DEC11(CreateDir);
DEC11(DeleteFile);
DEC11(LoadSeg);
DEC21(Lock);
DEC21(MatchFirst);
DEC21(NewLoadSeg);
DEC21(Open);
DEC21(SetComment);
DEC21(SetFileDate);
DEC21(SetProtection);
/* manually declared, because different from standard */
LONG (*ASM oldMakeLink) (REG(d1) UBYTE *, REG(d2) LONG, REG(d3) LONG, REG(a6) struct Library *);
SAVEDS LONG ASM newMakeLink(REG(d1) UBYTE *, REG(d2) LONG, REG(d3) LONG, REG(a6) struct Library *);
extern LVOMakeLink;
LONG (*ASM oldRename) (REG(d1) UBYTE *, REG(d2) UBYTE *, REG(a6) struct Library *);
SAVEDS LONG ASM newRename(REG(d1) UBYTE *, REG(d2) UBYTE *, REG(a6) struct Library *);
extern LVORename;
LONG (*ASM oldParsePattern) (REG(d1) UBYTE *, REG(d2) UBYTE *, REG(d3) LONG, REG(a6) struct Library *);
SAVEDS LONG ASM newParsePattern(REG(d1) UBYTE *, REG(d2) UBYTE *, REG(d3) LONG, REG(a6) struct Library *);
extern LVOParsePattern;
struct LVOTable LVOArrayUnixDirs[] =
{
{(LONG)&LVOCreateDir, (struct Library *)&DOSBase, (ULONG)&oldCreateDir, (ULONG)&newCreateDir },
{(LONG)&LVODeleteFile, (struct Library *)&DOSBase, (ULONG)&oldDeleteFile, (ULONG)&newDeleteFile },
{(LONG)&LVOLoadSeg, (struct Library *)&DOSBase, (ULONG)&oldLoadSeg, (ULONG)&newLoadSeg },
{(LONG)&LVOLock, (struct Library *)&DOSBase, (ULONG)&oldLock, (ULONG)&newLock },
{(LONG)&LVONewLoadSeg, (struct Library *)&DOSBase, (ULONG)&oldNewLoadSeg, (ULONG)&newNewLoadSeg },
{(LONG)&LVOOpen, (struct Library *)&DOSBase, (ULONG)&oldOpen, (ULONG)&newOpen },
{(LONG)&LVOSetComment, (struct Library *)&DOSBase, (ULONG)&oldSetComment, (ULONG)&newSetComment },
{(LONG)&LVOSetFileDate, (struct Library *)&DOSBase, (ULONG)&oldSetFileDate, (ULONG)&newSetFileDate },
{(LONG)&LVOSetProtection, (struct Library *)&DOSBase, (ULONG)&oldSetProtection, (ULONG)&newSetProtection },
{(LONG)&LVOAssignLate, (struct Library *)&DOSBase, (ULONG)&oldAssignLate, (ULONG)&newAssignLate },
{(LONG)&LVOAssignPath, (struct Library *)&DOSBase, (ULONG)&oldAssignPath, (ULONG)&newAssignPath },
{(LONG)&LVORename, (struct Library *)&DOSBase, (ULONG)&oldRename, (ULONG)&newRename },
{(LONG)&LVOMakeLink, (struct Library *)&DOSBase, (ULONG)&oldMakeLink, (ULONG)&newMakeLink },
{(LONG)&LVOMatchFirst, (struct Library *) & DOSBase, (ULONG)&oldMatchFirst, (ULONG)&newMatchFirst },
{(LONG)&LVOParsePattern, (struct Library *) & DOSBase, (ULONG)&oldParsePattern, (ULONG)&newParsePattern }
};
struct UnixDirsJumpTable
{
struct SignalSemaphore jt_Semaphore;
UWORD pad_word;
struct Task *jt_Owner;
UBYTE jt_Function[UNIXDIRS_NUMBEROFFUNCTIONS * 6];
};
/* Strings */
/* The name this JumpTable/Semaphore will get. */
static UBYTE *UnixDirsJTName = "YakUnixDirs-JT";
static BOOL UnixDirsPatchInstalled = FALSE;
__regargs void
ToggleUnixDirs( BOOL toggle )
{
if (toggle == TRUE)
{
if (UnixDirsPatchInstalled == FALSE)
{
InstallWedge(UnixDirsJTName,
LVOArrayUnixDirs,
(UBYTE) UNIXDIRS_NUMBEROFFUNCTIONS);
UnixDirsPatchInstalled = TRUE;
}
}
else
{
if (UnixDirsPatchInstalled == TRUE)
{
RemoveWedge(UnixDirsJTName,
LVOArrayUnixDirs,
(UBYTE) UNIXDIRS_NUMBEROFFUNCTIONS);
UnixDirsPatchInstalled = FALSE;
}
}
}
/******************************************************************************/
/******************* **************************/
/******************* NEW DOS ROUTINES START HERE **************************/
/******************* **************************/
/******************************************************************************/
/********************************************
Example of the simplest patch (does nothing)
SAVEDS LONG ASM
new(REG(d1) LONG arg1, REG(d2) LONG arg2,
REG(a6) struct Library *base)
{
return old(arg1, arg2, base);
}
********************************************/
/*
* These are the generic patch routines.
* They handle most patches automatically.
*/
#define PATHSIZE 512L /* enough for most purposes? */
/* 1 args, convert arg in d1 */
LONG ASM Wedge11 (REG(a0) LONG (*ASM dosroutine)(REG(d1) UBYTE *, REG(a6) struct Library *),
REG(d1) UBYTE *arg1,
REG(a6) struct Library *base)
{
struct SignalSemaphore *jt;
UBYTE *newpath;
LONG rc = 0;
if (jt = FindSemaphore(UnixDirsJTName))
{
ObtainSemaphoreShared(jt);
if (newpath = AllocVec(PATHSIZE, 0L))
{
if (adjustpath(arg1, newpath, PATHSIZE))
rc = dosroutine(newpath, base);
else
rc = dosroutine(arg1, base);
FreeVec(newpath);
}
else SetIoErr(ERROR_NO_FREE_STORE);
ReleaseSemaphore(jt);
}
return rc;
}
/* 2 args, convert arg in d1 */
LONG ASM Wedge21 (REG(a0) LONG (*ASM dosroutine)(REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *),
REG(d1) UBYTE *arg1,
REG(d2) LONG arg2,
REG(a6) struct Library *base)
{
struct SignalSemaphore *jt;
UBYTE *newpath;
LONG rc = 0;
if (jt = FindSemaphore(UnixDirsJTName))
{
ObtainSemaphoreShared(jt);
if (newpath = AllocVec(PATHSIZE, 0L))
{
if (adjustpath(arg1, newpath, PATHSIZE))
rc = dosroutine(newpath, arg2, base);
else
rc = dosroutine(arg1, arg2, base);
FreeVec(newpath);
}
else SetIoErr(ERROR_NO_FREE_STORE);
ReleaseSemaphore(jt);
}
return rc;
}
/* 2 args, convert arg in d2 */
LONG ASM Wedge22 (REG(a0) LONG (*ASM dosroutine)(REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *),
REG(d1) LONG arg1,
REG(d2) UBYTE *arg2,
REG(a6) struct Library *base)
{
struct SignalSemaphore *jt;
UBYTE *newpath;
LONG rc = 0;
if (jt = FindSemaphore(UnixDirsJTName))
{
ObtainSemaphoreShared(jt);
if (newpath = AllocVec(PATHSIZE, 0L))
{
if (adjustpath(arg2, newpath, PATHSIZE))
rc = dosroutine(arg1, newpath, base);
else
rc = dosroutine(arg1, arg2, base);
FreeVec(newpath);
}
else SetIoErr(ERROR_NO_FREE_STORE);
ReleaseSemaphore(jt);
}
return rc;
}
#define PATCH11(name) \
SAVEDS LONG ASM \
new## name(REG(d1) UBYTE *arg1, \
REG(a6) struct Library *base) \
{ return Wedge11(old## name, arg1, base); }
#define PATCH21(name) \
SAVEDS LONG ASM \
new## name(REG(d1) UBYTE *arg1, REG(d2) LONG arg2, \
REG(a6) struct Library *base) \
{ return Wedge21(old## name, arg1, arg2, base); }
#define PATCH22(name) \
SAVEDS LONG ASM \
new## name(REG(d1) LONG arg1, REG(d2) UBYTE *arg2, \
REG(a6) struct Library *base) \
{ return Wedge22(old## name, arg1, arg2, base); }
PATCH22(AssignLate)
PATCH22(AssignPath)
PATCH11(CreateDir)
PATCH11(DeleteFile)
PATCH11(LoadSeg)
PATCH21(Lock)
PATCH21(MatchFirst)
PATCH21(NewLoadSeg)
PATCH21(Open)
PATCH21(SetComment)
PATCH21(SetFileDate)
PATCH21(SetProtection)
/*** And the following routines are handmade ***/
SAVEDS LONG ASM
newRename(REG(d1) UBYTE *oldname, REG(d2) UBYTE *newname,
REG(a6) struct Library *base)
{
struct SignalSemaphore *jt;
UBYTE *from, *to;
LONG rc = 0;
if (jt = FindSemaphore(UnixDirsJTName))
{
ObtainSemaphoreShared(jt);
if (from = AllocVec(PATHSIZE, 0L))
{
adjustpath(oldname, from, PATHSIZE);
if (to = AllocVec(PATHSIZE, 0L))
{
adjustpath(newname, to, PATHSIZE);
rc = oldRename(from, to, base);
FreeVec(to);
}
else SetIoErr(ERROR_NO_FREE_STORE);
FreeVec(from);
}
else SetIoErr(ERROR_NO_FREE_STORE);
ReleaseSemaphore(jt);
}
return rc;
}
/* a bit more suspect this; will buflen be big enough given a . substitution? */
SAVEDS LONG ASM
newParsePattern(REG(d1) UBYTE *pat,
REG(d2) UBYTE *buf,
REG(d3) LONG buflen,
REG(a6) struct Library *base)
{
struct SignalSemaphore *jt;
UBYTE *newpat;
LONG rc = 0;
if (jt = FindSemaphore(UnixDirsJTName))
{
ObtainSemaphoreShared(jt);
if (newpat = AllocVec(PATHSIZE, 0L))
{
adjustpath(pat, newpat, PATHSIZE);
rc = oldParsePattern(newpat, buf, buflen, base);
FreeVec(newpat);
}
else SetIoErr(ERROR_NO_FREE_STORE);
ReleaseSemaphore(jt);
}
return rc;
}
SAVEDS LONG ASM
newMakeLink (REG(d1) UBYTE *name,
REG(d2) LONG dest,
REG(d3) LONG soft,
REG(a6) struct Library *base)
{
struct SignalSemaphore *jt;
UBYTE *from, *to;
LONG rc = 0;
if (jt = FindSemaphore(UnixDirsJTName))
{
ObtainSemaphoreShared(jt);
if (from = AllocVec(PATHSIZE, 0L))
{
adjustpath(name, from, PATHSIZE);
if (soft)
{
/* dest points to a null-terminated path string */
if (to = AllocVec(PATHSIZE, 0L))
{
adjustpath((STRPTR)dest, to, PATHSIZE);
rc = oldMakeLink(from, (LONG)to, soft, base);
FreeVec(to);
}
else SetIoErr(ERROR_NO_FREE_STORE);
}
else
{
/* dest is a lock (BPTR) */
rc = oldMakeLink(from, dest, soft, base);
}
FreeVec(from);
}
else SetIoErr(ERROR_NO_FREE_STORE);
ReleaseSemaphore(jt);
}
return rc;
}
/*
* Routine to convert a UNIX-style path to an AmigaDOS path.
* A UNIX-style path is understood here as follows:
*
* leading . means current dir; like "", but filled in explicitly
* ../ means /
* .. means /
*
* Written as part of UnixDirs2, a (to be written) system patch which allows
* use of UNIX-style paths everywhere.
*
* Martin W. Scott, 8 January 1993
*/
/* insert $cwd into s, return pointer to next free char */
SAVEDS char *
insertcwd(char *s, LONG len)
{
if (NameFromLock(((struct Process *)(((struct ExecBase *)SysBase)->ThisTask))->pr_CurrentDir, s, len))
{
while (*s)
s++;
}
return s;
}
/* adjust path from UNIX-style to Amiga-style */
/* TO DO: length checking when building new path */
SAVEDS BOOL
adjustpath(UBYTE *path, UBYTE *newpath, LONG len)
{
UBYTE *s, *t;
#ifdef DEBUG
char *origpath = path;
#endif
s = newpath;
if (path == NULL) /* bypass */
return FALSE;
if (slashdir && (path[0] == '/'))
{
path[0]=':'; /* to accommodate unix-style root paths */
}
if (t = strchr(path, ':')) /* check for ':' in path */
{
t++; /* copy device component */
while (path < t)
*s++ = *path++;
}
else if (path[0] == '.') /*** translate '.' to $cwd ***/
{
if (!path[1]) /* only "." */
{
s = insertcwd(s, len);
path++; /* path[0] == '\0' - STOP */
}
else if (path[1] == '/') /* initial component is $cwd */
{
s = insertcwd(s, len);
if (*(s-1) != ':')
*s++ = '/'; /* copy '/', increment pointers */
path += 2;
}
}
while (path[0]) /*** copy remainder of path ***/
{
if (path[0] == '.' && path[1] == '.')
{
if (path[2] == '/') /* just skip "..", copying '/' */
{
path += 2;
*s++ = *path++;
}
else if (!path[2]) /* append '/' and stop */
{
path += 2;
*s++ = '/';
}
else *s++ = *path++;
}
else *s++ = *path++;
}
*s = '\0';
return TRUE;
}